//==============================================================================
// GenBankEntry.cc
// ----------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
// $Id: GenBankEntry.cc,v 1.1 2000/01/31 21:13:16 kdurbin Exp $
//------------------------------------------------------------------------------
// $Log: GenBankEntry.cc,v $
// Revision 1.1  2000/01/31 21:13:16  kdurbin
// Initial revision
//
//   
//==============================================================================
//.......1.........2.........3.........4.........5.........6.........7.........8
//

#include "GenBankEntry.hh"


char gLineBuffer[LINE_BUFFER_SIZE];

//---------------------------------------------------------------------------
// * Print
//---------------------------------------------------------------------------
// 
void 
GenBankEntry::Print(ostream &out)
{
  for(int i =0;i<(*this).mFeatures.size();i++){
	 (*this).mFeatures[i].Print(out);
	 cout<<endl;
  }
}


void 
GenBankEntry::PrintFeatures(ostream &out, string &fname)
{
  for(int i = 0;i< mFeatures.size();i++){
	 if (mFeatures[i].mName == fname){
		mFeatures[i].Print(out);
		cout<<endl;
	 }
  }
}


bool
GenBankEntry::GetNextFeature(string &fname,int &fIdx,GenBankFeature &F)
{
  if((fIdx < 0) || (fIdx >= mFeatures.size())) return(false);

  for(int i = fIdx; i<mFeatures.size();i++){
	 if (Contains(mFeatures[i].mName,fname)){
		F = mFeatures[i];
		fIdx = i+1;
		return(true);
	 }
  } 
  fIdx = -1;
  return(false);
}


void
GenBankEntry::ParseFeatureLocs(string &LocStr,GenBankFeature &f)
{

  if (Contains(LocStr,"complement")) f.mbComplement = true;
  else f.mbComplement = false;

  vector<int> locVec;
  //  GetAllDelimitedIntsFromLine(LocStr,locVec);
  GetAllIntegers(LocStr,locVec);
  GenBankLocs tempL; 
  for(int i = 0;i< locVec.size();i++){
	 if (locVec.size() > (i+1)){
		tempL.mStart = locVec[i];
		i++;
		tempL.mEnd = locVec[i];
		f.mLocs.push_back(tempL);
	 }else{
		tempL.mStart = locVec[i];
		tempL.mEnd = locVec[i];
	 }
  }
  LocStr="";
}


void
GenBankEntry::ParseComment(string &CommentStr,GenBankFeature &f)
{

  GenBankComment tempC;
  int slashIdx = CommentStr.find("/");
  int eqIdx = CommentStr.find("=");
  
  tempC.mName = CommentStr.substr(slashIdx+1,(eqIdx-slashIdx-1));

  int firstQuote = CommentStr.find("\"");
  int secondQuote = CommentStr.find("\"",firstQuote+1);
  
  tempC.mText = CommentStr.substr(firstQuote+1,(secondQuote-firstQuote-1));
  f.mComments.push_back(tempC);
  CommentStr="";
}

void
GenBankEntry::ParseSequenceFromStream(ifstream &fin,Sequence &seq)
{
  string line;
  do{
	 fin.getline(gLineBuffer,LINE_BUFFER_SIZE);
	 line = gLineBuffer;
	 if (!Contains(line,"//")){
		line = SequenceField(line);
		StripWhiteSpace(line);
		for(int i = 0;i< line.size();i++){
		  seq.push_back(line[i]);
		}
	 }
  }while((!fin.eof()) && (!Contains(line,"//")));
}

string 
GenBankEntry::SequenceField(string &line){
  return(line.substr(10,(line.size()-10)));
}

string 
GenBankEntry::KeywordField(string &Line){
  return(Line.substr(0,20));
}

string 
GenBankEntry::ContentField(string &Line){
  return(Line.substr(21,(Line.size()-20)));
}





void
GenBankEntry::ParseFeatureLines(vector<string>&fLines,GenBankFeature &feature)
{
  int i = 0;
  string fLocs="",fComment="";
  // Get all the lines involved in the feature locations
  while(i< fLines.size()){
	 if (Contains(fLines[i],"/")) break;
	 string fLocsBit = ContentField(fLines[i]);
	 fLocs += fLocsBit;
	 i++;
  };
  
  ParseFeatureLocs(fLocs,feature);  

  while(i< fLines.size()){
	 // new comment found, otherwise part of previous comment
	 if (Contains(fLines[i],"/")){
		// Parse the previous one and save it in feature. 
		if (fComment != "") ParseComment(fComment,feature);
		fComment = fLines[i];
	 }else{
		
		fComment+=" ";
		fComment+=ContentField(fLines[i]);
	 }
	 i++;
  };
  if (fComment != "") ParseComment(fComment,feature);
  fLines.clear();
}



bool
GenBankEntry::ParseGenBankFile(string &FileName)
{
  ifstream fin;
  fin.open(FileName.c_str(),ios::in);
  if (fin.fail()){
	 cout<<FileName<<" file open failed (Read Multiple FASTA)"<<endl;
	 return(false);
  }
	
  GenBankFeature feature;
  string line;
  vector<string> featureLines;

  // Skip everything up to the keyword FEATURES
  do{
	 fin.getline(gLineBuffer,LINE_BUFFER_SIZE);
	 line = gLineBuffer;
  }while(!Contains(line,"source"));

  // Get each chunk of lines associated with a feature, and
  // then parse the feature. 
  do{
	 string featureName = KeywordField(line);
	 StripWhiteSpace(featureName);
	 // if we find a new feature, parse the previous one, and add the 
	 // feature to the list. 
	 if (featureName != ""){
		if (featureLines.size() > 0){
		  ParseFeatureLines(featureLines,feature);
		  mFeatures.push_back(feature);
		  feature.clear();
		}
		feature.mName = featureName;
		featureLines.push_back(line);
	 }else{
		featureLines.push_back(line);
	 }
	 fin.getline(gLineBuffer,LINE_BUFFER_SIZE);
	 line = gLineBuffer;

  }while((!fin.eof()) && (!Contains(line,"BASE COUNT")));
  fin.getline(gLineBuffer,LINE_BUFFER_SIZE);  // Get the line that says ORIGIN

  // Now, we've come to the sequence
  ParseSequenceFromStream(fin,mSequence);
}






